Skip to content

fix: clear reverseRpcDisposers array after disposing handlers - #5

Closed
hobostay wants to merge 1 commit into
MoonshotAI:mainfrom
hobostay:fix/reverse-rpc-double-dispose
Closed

fix: clear reverseRpcDisposers array after disposing handlers#5
hobostay wants to merge 1 commit into
MoonshotAI:mainfrom
hobostay:fix/reverse-rpc-double-dispose

Conversation

@hobostay

Copy link
Copy Markdown

Summary

  • clearReverseRpcPanels disposed all handlers but did not clear the array
  • On session switches via unloadCurrentSession, the old already-disposed entries remained, causing double-dispose on the next call
  • Added this.reverseRpcDisposers.length = 0 after the loop, matching the cleanup pattern already used in the stop() method

Test plan

  • Verify TUI session switching works correctly
  • Confirm no double-dispose errors after multiple session switches

🤖 Generated with Claude Code

clearReverseRpcPanels disposed all handlers but did not clear the
array. On session switches via unloadCurrentSession, the old
already-disposed entries remained, causing double-dispose on the
next call. This matches the cleanup pattern already used in stop().

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@liruifengv

Copy link
Copy Markdown
Collaborator

Thank you for your interest in contributing to kimi-code.
However, we currently do not accept bulk AI-generated submissions that have not undergone thorough human review, so we will be closing these PR.

@liruifengv liruifengv closed this May 23, 2026
chengluyu added a commit to chengluyu/kimi-code that referenced this pull request Jun 1, 2026
zha-ji-tui added a commit to zha-ji-tui/kimi-code that referenced this pull request Jun 1, 2026
- Gate the readdir fallback on `gitCache.isGitRepo()` instead of `snapshot === null`, so a transient `git ls-files` failure inside a real git repo does not expose `.gitignore`d files. The previous gate conflated "not a git repo" with "git ls-files failed transiently".

- Break out of the per-entry `walkDir` loop once `READDIR_MAX_ENTRIES` is reached, so a single large directory does not `statSync` every remaining file after the cap is filled. The cap was previously only checked on entry to `walkDir`.

- Handle the snapshot-null case after the `isGitRepo()` gate to avoid NPE when `getSnapshot()` returns null transiently inside a real git repo.

- Add a transient-failure test (isGitRepo=true, getSnapshot=null) and extend `stubGitCache` to decouple `isGitRepo` from snapshot presence.

Refs PR MoonshotAI#268 codex review (P2 MoonshotAI#5, MoonshotAI#6).
sailist added a commit that referenced this pull request Jun 5, 2026
…imentalDecorators (P2.1)

Smoke test for Phase 2 @ifoo migration: switch
`services.set(IConnectionRegistry, new ConnectionRegistry())` to
`services.set(IConnectionRegistry, new SyncDescriptor(ConnectionRegistry))`
so the container drives construction through
`_createAndCacheServiceInstance` and the @ifoo auto-injection path.
ConnectionRegistry has 0 service deps so the auto-inject step is a no-op
— this is the minimum viable proof that the new path replaces ad-hoc
`new C()` registrations cleanly. Logger stays as an externally-built
`PinoLogger` instance (its ctor takes the pino DaemonLogger, not a DI
dependency).

Also enable `experimentalDecorators: true` in
`packages/{daemon,services}/tsconfig.json` — required prerequisite for
`@IFoo`-style parameter decorators landing in P2.2 onwards. The root
tsconfig stays untouched; only the two packages migrating to @ifoo opt
in. esbuild (vitest transpiler) and tsdown (rolldown bundler) both
honor this flag for legacy parameter-decorator emit.

Per phase-1 reviewer handoff #1: this is the smoke test confirming a
single descriptor-based registration migrates cleanly before fan-out.
agent-core/src/di/ untouched (sealed for Phase 2).

Daemon test green (241 pass after one flake-rerun on fs-watch.e2e.test.ts
AC #2 burst window — known flake per phase-1 reviewer handoff #5).

VERDICT: PASS — start.ts:296 descriptor swap + tsconfig
experimentalDecorators=true; 241/241 daemon tests green.
@trustmiao

Copy link
Copy Markdown

执行计划

需求确认

  • issue fix: clear reverseRpcDisposers array after disposing handlers #5 描述的问题是:clearReverseRpcPanels() 在逐个调用 reverseRpcDisposers 后没有清空数组,导致后续 unloadCurrentSession() 再次执行时重复 dispose 已失效的 handler。
  • 触发路径主要是 TUI session 切换/关闭:setSession()closeSession() -> unloadCurrentSession() -> clearReverseRpcPanels()
  • 当前工作区里已经能看到同方向的未提交改动:在 apps/kimi-code/src/tui/kimi-tui.tsclearReverseRpcPanels() 循环后添加 this.reverseRpcDisposers.length = 0,并在 apps/kimi-code/test/tui/kimi-tui-startup.test.ts 增加覆盖重复 close 不会重复调用 disposer 的测试。执行阶段需要先确认这些改动是否就是要纳入的实现,避免覆盖他人工作区内容。

影响范围

  • 主要代码:apps/kimi-code/src/tui/kimi-tui.ts
  • 测试落点:apps/kimi-code/test/tui/kimi-tui-startup.test.ts,因为这里已有 session 启停和 runtime state 相关 driver 测试。
  • 相关但不需要改动的模块:apps/kimi-code/src/tui/reverse-rpc/index.tsapps/kimi-code/test/tui/reverse-rpc/index.test.ts,它们负责注册/注销 UI hooks;本问题是 KimiTUI 持有 disposer 数组后的生命周期清理。

实施计划

  1. 保持改动最小:只在 clearReverseRpcPanels() dispose 循环结束后清空 reverseRpcDisposers 数组,使其和 stop() 里的清理模式一致。
  2. 增加或保留一个 startup 层回归测试:初始化 TUI driver 后注入一个 mock disposer,连续调用两次 closeSession(),断言 disposer 只调用一次且数组长度为 0。
  3. 检查是否有更合适的测试 helper 能避免过多暴露私有字段;若沿用类型 cast,只把它限制在测试文件内部的小接口里。
  4. 不改 reverse-rpc controller 行为,不调整 session close 顺序,避免扩大行为面。

验证计划

  • 运行定向测试:pnpm vitest run apps/kimi-code/test/tui/kimi-tui-startup.test.ts -t "clears reverse RPC disposers"
  • 运行相关 TUI startup 测试文件:pnpm vitest run apps/kimi-code/test/tui/kimi-tui-startup.test.ts
  • 运行格式/静态检查中最相关的检查;若时间允许,运行 pnpm --filter @moonshot-ai/kimi-code run typecheck
  • 该变更影响 TUI session 切换这一用户流程,不影响网页;执行阶段仍需要做一次 TUI 级别的 e2e/手动流程验证:启动 Kimi TUI,进行至少两次 session 切换或 resume/close 循环,确认没有 double-dispose 异常或残留 approval/question 面板。

风险

  • 当前仓库已有同文件未提交改动,执行阶段必须只处理本 issue 相关 diff,不能回滚或覆盖其它并行修改。
  • 单元测试能覆盖 disposer 数组生命周期,但真实终端 session 切换还依赖 SDK handler 与 UI panel 行为,因此需要补充 TUI 流程验证。

@trustmiao

Copy link
Copy Markdown

执行结果

实际修改

  • apps/kimi-code/src/tui/kimi-tui.ts: clearReverseRpcPanels() 在遍历调用 reverseRpcDisposers 后立即清空数组,避免后续 unloadCurrentSession() / closeSession() 再次重复 dispose 已失效 handler。
  • apps/kimi-code/test/tui/kimi-tui-startup.test.ts: 增加回归测试,注入 mock disposer 后连续调用两次 closeSession(),断言 disposer 只执行一次且数组被清空。

验证结果

  • PASS: corepack pnpm --config.engine-strict=false vitest run apps/kimi-code/test/tui/kimi-tui-startup.test.ts -t "clears reverse RPC disposers"
  • PASS: corepack pnpm --config.engine-strict=false --filter @moonshot-ai/kimi-code run typecheck
  • PASS: git diff --check -- apps/kimi-code/src/tui/kimi-tui.ts apps/kimi-code/test/tui/kimi-tui-startup.test.ts
  • PARTIAL: corepack pnpm --config.engine-strict=false vitest run apps/kimi-code/test/tui/kimi-tui-startup.test.ts 中 47/50 通过,3 个既有 resume command 引号期望失败(期望单引号,实际为双引号),与本次 reverse RPC disposer 生命周期修复无关。

环境说明

  • 当前本地 Node 为 v24.14.0,仓库要求 >=24.15.0,因此测试命令使用了 --config.engine-strict=false 才能在当前环境跑完。

未完成风险 / 需补充

  • 该改动影响 TUI session 切换/关闭用户流程,不影响网页。需要补做 TUI e2e test 或手动流程验证:启动 Kimi TUI,进行至少两次 session 切换或 resume/close 循环,确认没有 double-dispose 异常,approval/question 面板不残留。

@trustmiao

Copy link
Copy Markdown

调查阶段方案

标记:Workmonitor issue-flow investigation stage 20260618-133001 issue #5

需求确认

  • issue fix: clear reverseRpcDisposers array after disposing handlers #5 是一个已关闭 PR 线程,标题为 fix: clear reverseRpcDisposers array after disposing handlers
  • 问题描述:clearReverseRpcPanels() 遍历并 dispose reverseRpcDisposers 后没有清空数组;当 unloadCurrentSession() 在 session 切换、关闭、reload 等路径再次执行时,会对已经 dispose 过的 handler 再次 dispose。
  • 期望行为:dispose 后立即清空 reverseRpcDisposers,与 stop() 中已有的清理模式保持一致,避免多次 session close/switch 触发 double-dispose。

代码定位与影响范围

  • 主要代码:apps/kimi-code/src/tui/kimi-tui.ts
  • 注册点:KimiTUI 构造函数里调用 registerReverseRPCHandlers(...),并把返回的 disposer 保存到 reverseRpcDisposers
  • 清理路径:setSession() -> unloadCurrentSession('switching session')closeSession() -> unloadCurrentSession(reason)reloadCurrentSessionView() 直接调用 clearReverseRpcPanels()
  • 相关 reverse-rpc 模块:apps/kimi-code/src/tui/reverse-rpc/index.ts 只负责设置 approval/question UI hooks 并返回清理函数,问题不在 controller/adapter 行为,而在 KimiTUI 持有 disposer 数组后的生命周期管理。
  • 测试落点:apps/kimi-code/test/tui/kimi-tui-startup.test.ts 已有 startup/runtime state 测试,适合追加 close/session lifecycle 的窄回归测试。
  • 当前本地工作区已经存在与该问题一致的未提交差异:clearReverseRpcPanels() 循环后增加 this.reverseRpcDisposers.length = 0,并在 startup 测试里加入连续两次 closeSession() 只调用一次 disposer 的测试。执行阶段需要保留这个方向,同时注意工作区还有其它无关未提交改动,不能回滚或覆盖。

具体实施方案

  1. 保持最小改动:在 apps/kimi-code/src/tui/kimi-tui.tsclearReverseRpcPanels() 中,遍历调用所有 disposer 后执行 this.reverseRpcDisposers.length = 0
  2. 不改 registerReverseRPCHandlers()、approval/question controller、session handler 注册顺序,也不改变 session close/switch 的其它行为,避免扩大影响面。
  3. apps/kimi-code/test/tui/kimi-tui-startup.test.ts 增加或保留回归测试:构造 TUI driver 后替换 reverseRpcDisposers 为 mock disposer,连续调用两次 closeSession(),断言 disposer 只被调用一次且数组长度为 0。
  4. 若执行阶段发现私有字段 cast 影响可维护性,只把测试用接口限制在测试文件内,不新增生产代码可见 API。

验证方案

  • 定向回归:corepack pnpm --config.engine-strict=false vitest run apps/kimi-code/test/tui/kimi-tui-startup.test.ts -t "clears reverse RPC disposers"
  • 相关测试文件:corepack pnpm --config.engine-strict=false vitest run apps/kimi-code/test/tui/kimi-tui-startup.test.ts
  • 类型检查:corepack pnpm --config.engine-strict=false --filter @moonshot-ai/kimi-code run typecheck
  • Diff 基础检查:git diff --check -- apps/kimi-code/src/tui/kimi-tui.ts apps/kimi-code/test/tui/kimi-tui-startup.test.ts
  • 手动/TUI 流程验证:启动 Kimi TUI,执行至少两次 session switch 或 close/resume 循环,确认没有 double-dispose 异常,approval/question 面板不会残留。

风险与注意事项

  • 本问题影响 TUI session 生命周期,不影响网页服务或导出/API。
  • 单元测试能覆盖 disposer 数组生命周期;真实终端流程仍建议补一次手动或 e2e 验证。
  • 当前工作区有多处无关修改,执行阶段应只提交本 issue 相关的 kimi-tui.ts 和对应测试差异。

@trustmiao

Copy link
Copy Markdown

执行阶段结果补充

标记:Workmonitor issue-flow execute stage 20260618-133001 issue #5

实际修改内容

  • apps/kimi-code/src/tui/kimi-tui.ts: clearReverseRpcPanels() 在遍历调用 reverseRpcDisposers 后清空数组,避免后续 unloadCurrentSession()closeSession()reloadCurrentSessionView() 重复 dispose 已经失效的 reverse RPC UI handler。
  • apps/kimi-code/test/tui/kimi-tui-startup.test.ts: 增加 reverse RPC disposer 生命周期回归测试,注入 mock disposer 后连续调用两次 closeSession(),断言 disposer 只执行一次且数组长度归零。
  • 未改动 registerReverseRPCHandlers()、approval/question controller、session handler 注册顺序或其它 session lifecycle 行为。

验证结果

  • 已按 execute 阶段方案覆盖本 issue 的核心生命周期路径:重复 close/session unload 不应重复 dispose 同一批 reverse RPC disposer。
  • 必要验证项为:定向 vitest 回归、相关 startup 测试文件、@moonshot-ai/kimi-code typecheck、以及 git diff --check
  • 该补救动作本身只补发 GitHub 评论,没有再次修改代码,也没有重新运行测试。

未完成风险

  • 该变更影响 TUI session 切换/关闭用户流程,不影响网页、浏览器交互或后端 API。
  • 单元测试覆盖 disposer 数组生命周期;真实终端流程仍建议在最终合入前补一次 TUI 手动或 e2e 验证:至少两次 session switch 或 close/resume 循环,确认没有 double-dispose 异常,approval/question 面板不残留。
  • 当前工作区存在其它无关未提交改动;后续提交时应只纳入本 issue 相关的 kimi-tui.ts 和对应测试差异。

@trustmiao

Copy link
Copy Markdown

e2e 阶段补充结果

标记:Workmonitor issue-flow e2e stage 20260618-133001 issue #5

已执行命令与结果

  • node -v; corepack pnpm --config.engine-strict=false --filter @moonshot-ai/kimi-code run e2e:未进入测试。外层 corepack pnpm 可启动,但 package script 内部调用裸 pnpm,当前 Windows 环境中 pnpm 不在 PATH,报错 'pnpm' is not recognized as an internal or external command。当前 Node 为 v24.14.0,根仓库要求 >=24.15.0
  • corepack pnpm --config.engine-strict=false -r --filter './packages/*' run build:未完成。构建到 packages/node-sdk 时,其脚本 tsdown && pnpm run build:dts 再次被内部裸 pnpm 不在 PATH 阻塞。
  • corepack enable:未完成。尝试生成全局 pnpm shim 时被 Node 安装目录权限阻塞,报 EPERM: operation not permitted, open 'D:\programs\node.js\yarn'
  • 使用临时目录 shim 转发 pnpm -> corepack pnpm --config.engine-strict=false 后执行 pnpm --filter @moonshot-ai/kimi-code run e2e:仍未进入测试。项目 e2e script 在 Windows cmd 下包含 POSIX 写法,'./packages/*' 被当成带引号的字面 filter,导致 No projects matched the filters;后续 KIMI_E2E=1 也被 cmd 识别为命令,报 'KIMI_E2E' is not recognized as an internal or external command
  • 使用 PowerShell 等价拆分命令执行 pnpm -r --filter ./packages/* run build:PASS。packages/* 构建完成,包括 packages/node-sdkbuild:dts 和 API Extractor。

e2e 覆盖状态

  • 本仓库 apps/kimi-code 现有 e2e 是 Vitest 套件:apps/kimi-code/test/e2e/local-logging-export.e2e.test.ts 和 opt-in 的 real-llm-smoke.e2e.test.ts;没有发现与本 issue 直接对应的 Playwright/浏览器 e2e。
  • 本 issue 修改的是终端 TUI session 生命周期和 reverse RPC disposer 清理,不涉及网页、浏览器交互或后端 API。浏览器验证不适用。
  • 由于最新指令要求只做评论补救,我没有继续运行拆分后的 KIMI_E2E=1 vitest run test/e2e,也没有再修改代码。

仍有风险与替代验证建议

  • 仍缺少真实 TUI session switch / close-resume 端到端验证证据。建议后续在 Node >=24.15.0 且 Windows 兼容命令已拆分的环境下运行:先 pnpm -r --filter ./packages/* run build,再以 PowerShell 设置 $env:KIMI_E2E='1' 后执行 pnpm -C apps/kimi-code exec vitest run test/e2e
  • 现有 app e2e 并不直接覆盖 reverse RPC disposer double-dispose;真正相关的验证仍是已有 unit/regression 测试和一次 TUI 手动/e2e 流程:至少两次 session switch 或 close/resume 循环,确认没有 double-dispose 异常,approval/question 面板不残留。

@trustmiao

Copy link
Copy Markdown

最终总结

标记:Workmonitor issue-flow final stage 20260618-133001 issue #5

覆盖确认

  • 已重新读取 issue fix: clear reverseRpcDisposers array after disposing handlers #5 内容和全部评论。issue 描述的问题是 clearReverseRpcPanels() dispose reverse RPC handlers 后未清空 reverseRpcDisposers,导致 session switch/close/reload 路径后续可能 double-dispose。
  • 已有调查阶段评论:Workmonitor issue-flow investigation stage 20260618-133001 issue #5,覆盖需求确认、影响范围、实施方案和验证方案。
  • 已有执行阶段评论:Workmonitor issue-flow execute stage 20260618-133001 issue #5,覆盖实际修改内容、验证项和未完成风险。
  • 已有 e2e 阶段评论:Workmonitor issue-flow e2e stage 20260618-133001 issue #5,覆盖 e2e 尝试、Windows/Node 环境阻塞、替代构建验证和剩余风险。

最后修改方案与行为变化

  • apps/kimi-code/src/tui/kimi-tui.ts: 在 clearReverseRpcPanels() 遍历调用 disposer 后清空 this.reverseRpcDisposers.length = 0。这样 unloadCurrentSession()closeSession()setSession() 间接触发的 session switch,以及 reloadCurrentSessionView() 不会再次 dispose 同一批 reverse RPC UI handlers。
  • apps/kimi-code/test/tui/kimi-tui-startup.test.ts: 增加 reverse RPC disposer 生命周期回归测试,注入 mock disposer 后连续两次 closeSession(),确认 disposer 只调用一次且数组被清空。
  • 未扩大修改范围:不改 registerReverseRPCHandlers()、approval/question controllers、session handler 注册顺序或其它 session lifecycle 语义。

验证结果汇总

  • PASS: 定向回归测试 corepack pnpm --config.engine-strict=false vitest run apps/kimi-code/test/tui/kimi-tui-startup.test.ts -t "clears reverse RPC disposers"
  • PASS: corepack pnpm --config.engine-strict=false --filter @moonshot-ai/kimi-code run typecheck
  • PASS: git diff --check -- apps/kimi-code/src/tui/kimi-tui.ts apps/kimi-code/test/tui/kimi-tui-startup.test.ts
  • PARTIAL: 完整 apps/kimi-code/test/tui/kimi-tui-startup.test.ts 曾出现 3 个既有 resume command 引号期望失败,与 reverse RPC disposer 生命周期修复无关。
  • PASS: 使用 PowerShell 等价拆分命令执行 pnpm -r --filter ./packages/* run buildpackages/* 构建完成,包括 packages/node-sdkbuild:dts 和 API Extractor。

e2e test 状态

  • apps/kimi-code 现有 e2e 是 Vitest 套件,不是 Playwright/浏览器套件;本 issue 修改终端 TUI session 生命周期,不涉及网页、浏览器交互或后端 API,因此浏览器验证不适用。
  • 直接运行 @moonshot-ai/kimi-code 的 e2e script 在当前 Windows 环境未进入测试:内部裸 pnpm 不在 PATH、根仓库 Node 要求 >=24.15.0 而当前为 v24.14.0,并且 script 使用 POSIX 写法 KIMI_E2E=1,在 Windows cmd 下不可执行。
  • 已记录替代验证和后续建议:在 Node >=24.15.0、Windows 兼容命令拆分环境下,先构建 packages,再以 PowerShell 设置 $env:KIMI_E2E='1' 运行 pnpm -C apps/kimi-code exec vitest run test/e2e;现有 app e2e 也不直接覆盖 reverse RPC double-dispose,真正相关验证仍是新增 unit/regression 和一次 TUI switch/close-resume 流程验证。

残余风险与关闭状态

  • 残余风险:缺少真实终端 TUI session switch / close-resume 端到端证据;建议合入前补一次手动或 TUI e2e 流程,确认没有 double-dispose 异常,approval/question 面板不残留。
  • 需求主体已经覆盖:代码方案、关键文件行为变化、回归测试、类型/格式检查、e2e 状态与阻塞说明均已评论记录。
  • issue 当前已经是 CLOSED 状态;本阶段无额外阻塞关闭原因。

@trustmiao

Copy link
Copy Markdown

Workmonitor issue-flow final stage 20260618-133001 issue #5

final_summary 阶段补充

已完成内容确认

  • 已重新读取 issue fix: clear reverseRpcDisposers array after disposing handlers #5 内容和全部评论,确认 investigation、execute、e2e 三个阶段均已有记录。
  • issue 原始需求是修复 clearReverseRpcPanels() dispose reverse RPC handlers 后未清空 reverseRpcDisposers,导致 session switch/close/reload 后续可能 double-dispose 的问题。
  • 最终方案是保持最小改动:clearReverseRpcPanels() 遍历 disposer 后执行 this.reverseRpcDisposers.length = 0,并增加重复 closeSession() 不会重复调用 disposer 的回归测试。

关键文件与行为变化

  • apps/kimi-code/src/tui/kimi-tui.ts: reverse RPC disposer 清理后数组归零,避免旧 handler 在后续 session lifecycle 路径中再次 dispose。
  • apps/kimi-code/test/tui/kimi-tui-startup.test.ts: 覆盖连续两次 closeSession() 时 mock disposer 只调用一次,且 reverseRpcDisposers 最终为空。
  • 未改变 reverse-rpc controller、approval/question handler 注册逻辑或 session close/switch 的其它语义。

验证与 e2e 状态

  • 已记录定向回归测试、typecheck、diff check 的通过结果。
  • 已记录完整 startup 测试文件中 3 个既有 resume command 引号期望失败,与本 issue 修改无关。
  • e2e 阶段已尝试运行 @moonshot-ai/kimi-code e2e,但当前 Windows/Node 环境存在阻塞:Node 为 v24.14.0,仓库要求 >=24.15.0;package script 内部裸 pnpm 不在 PATH;并且 KIMI_E2E=1 POSIX 写法在 Windows cmd 下不可执行。
  • 已完成替代验证:使用 PowerShell 等价拆分命令成功构建 packages/*,包括 packages/node-sdkbuild:dts 和 API Extractor。

残余风险与关闭状态

  • 残余风险是仍缺少真实 TUI session switch / close-resume 端到端验证证据;建议在 Node >=24.15.0 且命令按 Windows 兼容方式拆分后补跑一次 TUI 手动或 e2e 流程。
  • 需求主体已覆盖:方案、代码行为变化、回归测试、验证结果、e2e 阻塞和替代验证均已记录。
  • issue fix: clear reverseRpcDisposers array after disposing handlers #5 当前已经是 CLOSED 状态;本补救动作只补发 final_summary 评论,不修改代码、不改变 issue 状态。

wintrover added a commit to wintrover/kimy that referenced this pull request Jun 29, 2026
- kimy wrapper: move hash writes after smoke test (MoonshotAI#1)
- kimy wrapper: add public/ to web hash inputs (MoonshotAI#3)
- kimy wrapper: widen vis hash to include config files (MoonshotAI#4)
- kimy wrapper: move lockfile from /tmp to ~/.kimy/bin (MoonshotAI#5)
- kimy wrapper: use explicit package list for native hash (MoonshotAI#7)
- 01-bundle.mjs: skip vis-asset build when already done (MoonshotAI#2)
- justfile: sync deploy with new wrapper, add deploy-full (MoonshotAI#9,MoonshotAI#10,MoonshotAI#11)
- flake.nix: add unpin guidance to nixpkgs comment (MoonshotAI#12)
asdshuaishuai pushed a commit to d2rabbit/kimi-code that referenced this pull request Jul 21, 2026
MarkdownRenderer.svelte now picks the rendering surface based on the
content type of each fenced code block:

  · JSON blocks (cb-json): a collapsible tree is rendered alongside the
    raw code. Objects/arrays carry a ▾ caret that folds their children;
    strings green, numbers amber, booleans accent, null grey-italic.
    Trees deeper than 5K characters fall back to plain code (tree DOM
    would be sluggish past that). The raw <pre> stays visible so the
    user can still copy or read the original.

  · HTML blocks (cb-html): the code header bar gains a 👁 预览 button.
    Clicking injects a sandboxed <iframe srcdoc=...> below the code so
    the user can see what the snippet renders as, without running any
    scripts (sandbox='allow-same-origin' only — no allow-scripts).

  · Code headers (all langs): language label + copy button stay as
    before; HTML blocks additionally get the preview toggle.

  · Streaming still skips shiki and the JSON tree (latency-sensitive);
    both kick in once streaming=false.

ToolCard.svelte is rebuilt around a few ergonomic asks:

  · Status badge — color-coded pill (运行中 / 完成 / 失败) next to the
    tool name, in addition to the existing dot. Easier to scan at a
    glance than color alone.

  · Copy buttons — the expand area now has a small toolbar with
    '复制命令' (bash only) and '复制输出'. Both toast on success.

  · JSON output — when a tool's output parses as JSON, we render a
    <details> with pretty-printed JSON instead of the raw line view.
    Catches a lot of MCP / structured-tool responses.

  · Auto-expand running tools — when a tool transitions from
    idle/completed back to running, expanded flips to true so the user
    sees what's happening without a manual click.

  · All existing affordances kept: diff chip stats (+N/−M), click-to-
    preview file paths, bash terminal styling, line-numbered diff
    view for edit tools.

svelte-check 0 errors.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants